package com.dmg.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 数据源拦截器Aop 拦截所有的service方法
 * 设置aop优先执行 比事务管理器先执行
 * 如果事务管理器先执行，那么determineCurrentLookupKey()方法中，事务管理器在获取数据源的时候就是Null
 * 事务注解就不会生效
 */
@Order(0)
@Slf4j
@Aspect
@Component
public class DataSourceAspect {

    @Before("execution(* com.dmg.service.*.*(..))")
    public void setDataSourceKey(JoinPoint point) {
        log.info("进入拦截器");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        if (attributes != null) {
            // 获取HttpServletRequest对象
            HttpServletRequest request = attributes.getRequest();
            // 获取请求头信息 租户id
            String zuHuId = request.getHeader("zuHuId");
            //放入本地线程全局上下文中
            DataSourceContextHolder.setDataSourceKey(zuHuId);
        }
    }

    @After("execution(* com.dmg.service.*.*(..))")
    public void clearDataSourceKey() {
        log.info("离开拦截器");
        //离开方法之后 删除本地线程上下文的数据 防止内存泄漏
        DataSourceContextHolder.clearDataSourceKey();
    }
}